package com.lablzh.gdxy.service.impl;

import com.lablzh.gdxy.component.BCryptPasswordEncoderUtil;
import com.lablzh.gdxy.component.DynamicOperateExcelUtils;
import com.lablzh.gdxy.component.Md5Util;
import com.lablzh.gdxy.component.UserDetailsUtil;
import com.lablzh.gdxy.entity.*;
import com.lablzh.gdxy.entity.admin.Parameter;
import com.lablzh.gdxy.entity.assistant.Assistant;
import com.lablzh.gdxy.repository.*;
import com.lablzh.gdxy.repository.admin.ParameterRepository;
import com.lablzh.gdxy.repository.assistant.AssistantRepository;
import com.lablzh.gdxy.repository.practice.PracticeRepository;
import com.lablzh.gdxy.service.FileService;
import com.lablzh.gdxy.service.UserService;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;


@Service
public class UserServiceImpl implements UserService {
    private static final String BASEPATH = "./resources/static/";
    @Autowired
    private AssistantRepository assistantRepository;
    @Autowired
    private ParameterRepository parameterRepository;
    @Autowired
    private StudentRepositoty studentRepositoty;
    @Autowired
    private TeacherRepository teacherRepository;
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private InstructorRepository instructorRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ResetRepository resetRepository;
    @Autowired
    private BCryptPasswordEncoderUtil bCryptPasswordEncoderUtil;
    @Autowired
    Md5Util md5Util;
    @Autowired
    private UserDetailsUtil userDetailsUtil;
    @Autowired
    private FileService fileService;
    @Autowired
    private PracticeRepository practiceRepository;

//    public static boolean isRowEmpty(Row row){
//
//        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
//            Cell cell = row.getCell(i);
//            if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK){
//
//                return false;
//            }else {
//
//                break;
//            }
//        }
//        return true;
//    }


    /**
     * 学生注册
     *
     * @param student
     * @return
     */
    @Override
    public String addStudent1(Student student) {

        User user = new User();
        user.setUsername(student.getStID());
        user.setPassword(bCryptPasswordEncoderUtil.encode(student.getPassword()));
        user.setRole(student.getRole());
        userRepository.save(user);
        return "注册成功!";

    }

    @Override
    @CacheEvict(cacheNames = "teacher", allEntries = true)
    public String addTeacher1(Teacher teacher) {
        if (teacher != null) {
            if (teacherRepository.findAllByUsername(teacher.getUsername()) != null) {
                return "该用户名已存在";
            }

            User user = new User();
            user.setUsername(teacher.getUsername());
            user.setPassword(bCryptPasswordEncoderUtil.encode(teacher.getPassword()));
            user.setRole(teacher.getRole());
            userRepository.save(user);
            return "注册成功";
        } else {
            return "用户对象为空";
        }
    }

    @Override
    public String addStudent(Student student) {
        if (student != null) {
            if (studentRepositoty.findAllByStID(student.getStID()) != null) {
                return "该学号已经存在";
            }
            User user = new User();
            user.setUsername(student.getStID());
            user.setPassword(bCryptPasswordEncoderUtil.encode(student.getPassword()));
            user.setRole(student.getRole());
            student.setAudit("已审");
            studentRepositoty.save(student);
            userRepository.save(user);
            return "注册成功!";
        } else {
            return "用户对象为空";
        }
    }


    @Override
    @CacheEvict(cacheNames = "teacher", allEntries = true)
    public String addTeacher(Teacher teacher) {
        if (teacher != null) {
            if (teacherRepository.findAllByUsername(teacher.getUsername()) != null) {
                return "该用户名已存在";
            }
            if (userRepository.findAllByUsername(teacher.getUsername()) != null) {
                return "该用户名已存在";
            }
            teacher.setIsdirectorteacher("0");
            teacherRepository.save(teacher);
            User user = new User();
            user.setUsername(teacher.getUsername());
            user.setPassword(bCryptPasswordEncoderUtil.encode(teacher.getPassword()));
            user.setRole(teacher.getRole());
            userRepository.save(user);
            return "注册成功";
        } else {
            return "用户对象为空";
        }
    }

    @Override
    public String addAdmin(Admin admin) {
        if (admin != null) {
            if (adminRepository.findAllByUsername(admin.getUsername()) != null) {
                return "该用户名已存在";
            }
            if (userRepository.findAllByUsername(admin.getUsername()) != null) {
                return "该用户名已存在";
            }
            adminRepository.save(admin);
            User user = new User();
            user.setUsername(admin.getUsername());
            user.setPassword(bCryptPasswordEncoderUtil.encode(admin.getPassword()));
            user.setRole(admin.getRole());
            userRepository.save(user);
            return "注册成功";
        } else {
            return "用户对象为空";
        }
    }


    @Override
    public String addInstructor(Instructor instructor) {
        if (instructor != null) {
            if (instructorRepository.findAllByUsername(instructor.getUsername()) != null) {
                return "该用户名已存在";
            }
            if (userRepository.findAllByUsername(instructor.getUsername()) != null) {
                return "该用户名已存在";
            }
            instructorRepository.save(instructor);
            User user = new User();
            user.setUsername(instructor.getUsername());
            user.setPassword(bCryptPasswordEncoderUtil.encode(instructor.getPassword()));
            user.setRole(instructor.getRole());
            userRepository.save(user);
            return "注册成功";
        } else {
            return "用户对象为空";
        }
    }

    @Override
    @CacheEvict(cacheNames = "teacher", allEntries = true)
    public String deleteTeacher(Integer id) {
        String teacherUsername = teacherRepository.findById(id).orElse(null).getUsername();
        userRepository.deleteByUsername(teacherUsername);
        teacherRepository.deleteById(id);
        return "删除成功!";
    }

    @Override
    public String deleteStudent(Integer id) {
        String studentUsername = studentRepositoty.findById(id).orElse(null).getStID();
        userRepository.deleteByUsername(studentUsername);
        studentRepositoty.deleteById(id);
        return "删除成功！";
    }

    @Override
    public String deleteAdmin(Integer id) {
        String adminUsername = adminRepository.findById(id).orElse(null).getUsername();
        userRepository.deleteByUsername(adminUsername);
        adminRepository.deleteById(id);
        return "删除成功！";
    }

    @Override
    public String deleteInstructor(Integer id) {
        String instructorUsername = instructorRepository.findById(id).orElse(null).getUsername();
        userRepository.deleteByUsername(instructorUsername);
        instructorRepository.deleteById(id);
        return "删除成功！";
    }

    @Override
    public boolean checkLogin(String username, String rawPassword, String role) throws Exception {
        User user = userRepository.findAllByUsername(username);
        if(!user.getRole().equals(role))
        {
            throw new Exception("该账号角色异常");
        }

        switch (role) {
            case "student":
                if (studentRepositoty.findAllByStID(username) == null) {
                    throw new Exception("该角色不存在此账号！");
                }
                break;
            case "teacher":
                if (teacherRepository.findAllByUsername(username) == null) {
                    throw new Exception("该角色不存在此账号！");
                }
                break;
            case "admin":
                if (adminRepository.findAllByUsername(username) == null) {
                    throw new Exception("该角色不存在此账号！");
                }
                break;

            case "instructor":
                if (instructorRepository.findAllByUsername(username) == null) {
                    throw new Exception("该角色不存在此账号！");
                }
                break;
        }
        if (user == null) {
            throw new Exception("账号不存在，请重新尝试！");
        } else {
            //加密的密码
            String encodedPassword = user.getPassword();
            //和加密后的密码进行比配
            if (!bCryptPasswordEncoderUtil.matches(rawPassword, encodedPassword)) {
                //System.out.println("checkLogin--------->密码不正确！");
                //设置友好提示
                throw new Exception("密码不正确！");
            } else {
                return true;
            }
        }
    }

    @Override
    public String gainEmail(String role, String username) {
        if ("student".equals(role)) {
            Student student = studentRepositoty.findAllByStID(username);
            return student.getEmail();
        } else if ("teacher".equals(role)) {
            Teacher teacher = teacherRepository.findAllByUsername(username);
            return teacher.getEmail();
        } else {
            Admin admin = adminRepository.findAllByUsername(username);
            return admin.getEmail();
        }
    }

    @Override
    public String generateUrl(String basePath, String account, String username) throws Exception {
        String key = RandomStringUtils.randomAlphanumeric(6) + "";
        long outTime = System.currentTimeMillis() + (long) (30 * 60 * 1000);
        String sid = account + "&" + key + "&" + outTime;
        Reset reset0 = new Reset();
        reset0.setSid(md5Util.getMD5Str(sid));
        reset0.setOutTime(outTime);
        reset0.setUsername(username);
        reset0.setEmail(account);
        Reset reset = resetRepository.findByEmail(account);
        //存在的话就删除
        if (reset != null) {
            resetRepository.delete(reset);
        }
        resetRepository.save(reset0);
        return basePath + "register/reset_password?sid=" + md5Util.getMD5Str(sid) + "&username=" + username;
    }


    @Override
//    @CacheEvict(cacheNames = "student", allEntries = true)
    public String studentBatch(HttpServletRequest request) throws FileUploadException, IOException {
        List<Student> students = new ArrayList<>();
        List<User> users = new ArrayList<>();
        Workbook workbook = initWorkbook(request);
        Sheet sheet = workbook.getSheetAt(0);
        int count = 1;
        for (int rowNum = 1; rowNum < sheet.getLastRowNum(); rowNum++) {
            Student student = new Student();
            User user = new User();
            Row row = sheet.getRow(rowNum);
            Cell cell1 = row.getCell(0);
//            System.out.println(sheet.getLastRowNum());
            if (cell1.getCellType() == CellType.BLANK) {
//                System.out.println(rowNum);
                continue;
            }
            for (int i = 0; i < row.getLastCellNum(); i++) {
                Cell cell = row.getCell(i);
                cell.setCellType(CellType.STRING);
            }
            try {

                String username = row.getCell(0).getStringCellValue().trim();
                Student allByStID = studentRepositoty.findAllByStID(username);
                if(allByStID!=null)
                {
                    return "第" + count + "行学号已存在！";
                }
                System.out.println(username);
                String password = row.getCell(6).getStringCellValue().trim();
                student.setAudit("已审");
                student.setStID(username);
                student.setPassword(password);
                student.setName(row.getCell(1).getStringCellValue().trim());
                student.setCollege(row.getCell(2).getStringCellValue().trim());
                student.setMajor(row.getCell(3).getStringCellValue().trim());
                student.setClasses(row.getCell(4).getStringCellValue().trim());
                student.setPhone(row.getCell(7).getStringCellValue().trim());
                student.setEmail(row.getCell(8).getStringCellValue().trim());
                student.setBirth(row.getCell(10).getStringCellValue().trim());
                student.setRole("student");
                user.setUsername(username);
//                System.out.println(row.getCell(0).getStringCellValue().trim());
                user.setPassword(bCryptPasswordEncoderUtil.encode(password));
                user.setRole("student");
                students.add(student);
                users.add(user);
            } catch (NullPointerException e) {
                return "第" + count + "行有属性为空，请填满所有属性！";
            }
            count++;
        }
        try {

            System.out.println(users);
            System.out.println("fbgsejkg");
            studentRepositoty.saveAll(students);
            userRepository.saveAll(users);
//            System.out.println(students);
//            System.out.println(count);
//            System.out.println(students.size());
//            for (Student student : students) {
//                studentRepositoty.save(student);
//            }
//            for (User user: users) {
//                userRepository.save(user);
//            }
        } catch (Exception e) {
            return "表内学号冗余或有学号已存在！";
        }

        return "导入成功";
    }

    @Override
    @CacheEvict(cacheNames = "teacher", allEntries = true)
    public String teacherBatch(HttpServletRequest request) throws IOException, FileUploadException {
        List<Teacher> teachers = new ArrayList<>();
        List<User> users = new ArrayList<>();
        Workbook workbook = initWorkbook(request);
        Sheet sheet = workbook.getSheetAt(0);
        int count = 1;
        for (int rowNum = 1; rowNum < sheet.getLastRowNum(); rowNum++) {
            Teacher teacher = new Teacher();
            User user = new User();
            Row row = sheet.getRow(rowNum);
            Cell cell1 = row.getCell(0);
//            System.out.println(sheet.getLastRowNum());
            //防止读取空行
            if (cell1.getCellType() == CellType.BLANK) {
                System.out.println(rowNum);
                continue;
            }
            for (int i = 0; i < row.getLastCellNum(); i++) {
                Cell cell = row.getCell(i);
                cell.setCellType(CellType.STRING);
            }
            try {
                String password = row.getCell(5).getStringCellValue().trim();
                teacher.setUsername(row.getCell(4).getStringCellValue().trim());
                teacher.setPassword(password);
                teacher.setName(row.getCell(0).getStringCellValue().trim());
                teacher.setCollege(row.getCell(1).getStringCellValue().trim());
                teacher.setDepartment(row.getCell(2).getStringCellValue().trim());
                teacher.setLab(row.getCell(3).getStringCellValue().trim());
                teacher.setTitle(row.getCell(6).getStringCellValue().trim());
                teacher.setEmail(row.getCell(7).getStringCellValue().trim());
                teacher.setPhone(row.getCell(8).getStringCellValue().trim());
                teacher.setAddress(row.getCell(9).getStringCellValue().trim());
                teacher.setMajor(row.getCell(10).getStringCellValue().trim());
                teacher.setNote(row.getCell(11).getStringCellValue().trim());
                teacher.setRole("teacher");
                teacher.setIsdirectorteacher("0");
                teacher.setCourseInY(0);
                teacher.setCourseOutY(0);
                teacher.setDesignInY(0);
                teacher.setDesignOutY(0);
                teacher.setPracticeInY(0);
                teacher.setPracticeOutY(0);
                teacher.setExperimentAppointmentInY(0);
                teacher.setExperimentAppointmentOutY(0);
                teacher.setExperimentInY(0);
                teacher.setExperimentOutY(0);
                user.setUsername(row.getCell(4).getStringCellValue().trim());
                user.setPassword(bCryptPasswordEncoderUtil.encode(password));
                user.setRole("teacher");
                teachers.add(teacher);
                users.add(user);
            } catch (NullPointerException e) {
                return "第" + count + "行有属性为空，请填满所有属性！";
            }
            count++;
        }
        try {
            teacherRepository.saveAll(teachers);
            userRepository.saveAll(users);
        } catch (Exception e) {
            return "表内用户名冗余或用户名已存在！";
        }
        return "导入成功";
    }

    @Override
    public String arrangeSeat(Integer number, String classroom, HttpServletRequest request, HttpServletResponse response) throws FileNotFoundException {
        List<Integer> big_row = new ArrayList<>(Arrays.asList(3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5,
                6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13));
        List<Integer> big_column = new ArrayList<>(Arrays.asList(0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18,
                0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18));
        List<Integer> small_row = new ArrayList<>(Arrays.asList(2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5,
                7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9));
        List<Integer> small_column = new ArrayList<>(Arrays.asList(4, 8, 10, 14, 0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18,
                0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18, 0, 4, 8, 10, 14, 18));
        HashSet<String> big = new HashSet<>(Arrays.asList("s101", "s102"));
        HashSet<String> small = new HashSet<>(Arrays.asList("s107", "s108"));
        List<Integer> list = new ArrayList<>();//保存随机序号
        for (int k = 1; k <= number; k++) {
            list.add(k);
        }
        Collections.shuffle(list);
        if (big.contains(classroom)) {
            if (number > 42 || number < 1) {
                return "人数超出上限";
            }
            DynamicOperateExcelUtils dynamicOperateExcelUtils = new DynamicOperateExcelUtils("src/main/resources/static/" + "大教室座位安排模板.xlsx");
            dynamicOperateExcelUtils.replaceCellValue(1, 10, classroom);
            for (int i = 0; i < number; i++) {
                dynamicOperateExcelUtils.replaceCellValue(big_row.get(i), big_column.get(i), list.get(i));
            }
            dynamicOperateExcelUtils.exportExcel(new File(BASEPATH + classroom + "座位安排表.xlsx"));
            fileService.downloadFile(classroom + "座位安排表.xlsx", request, response);
        } else if (small.contains(classroom)) {
            if (number > 34 || number < 1) {
                return "人数超出上限";
            }
            DynamicOperateExcelUtils dynamicOperateExcelUtils = new DynamicOperateExcelUtils("src/main/resources/static/" + "小教室座位安排模板.xlsx");
            dynamicOperateExcelUtils.replaceCellValue(1, 13, classroom);
            for (int i = 0; i < number; i++) {
                dynamicOperateExcelUtils.replaceCellValue(small_row.get(i), small_column.get(i), list.get(i));
            }
            dynamicOperateExcelUtils.exportExcel(new File(BASEPATH + classroom + "座位安排表.xlsx"));
            fileService.downloadFile(classroom + "座位安排表.xlsx", request, response);
        } else {
            return "不存在该教室";
        }
        return "安排成功";
    }

    @Override
    public String assistantBatch(HttpServletRequest request) throws FileUploadException, IOException {
        List<Assistant> assistants = new ArrayList<>();
        Workbook workbook = initWorkbook(request);
        Sheet sheet = workbook.getSheetAt(0);
        int count = 1;
        for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Assistant assistant = new Assistant();
            System.out.println("!!!!!!!!!!!!!!!");
            System.out.println(sheet.getLastRowNum());
            Row row = sheet.getRow(rowNum);
            Cell cell1 = row.getCell(0);
//            System.out.println(sheet.getLastRowNum());
            //防止读取空行
            if (cell1.getCellType() == CellType.BLANK) {
                System.out.println(rowNum);
                continue;
            }
            System.out.println("====================");
            for (int i = 0; i < row.getLastCellNum(); i++) {
                Cell cell = row.getCell(i);
                cell.setCellType(CellType.STRING);
                System.out.println(row.getCell(i).getStringCellValue());
            }
            System.out.println("====================");
            try {
                assistant.setName(row.getCell(0).getStringCellValue());
                assistant.setCollege(row.getCell(1).getStringCellValue());
                assistant.setAddress(row.getCell(2).getStringCellValue());
                assistant.setMajor(row.getCell(3).getStringCellValue());
                assistant.setCategory(row.getCell(4).getStringCellValue());
                assistant.setGrade(row.getCell(5).getStringCellValue());
                assistant.setDepartment(row.getCell(6).getStringCellValue());
                assistant.setTeacher(row.getCell(7).getStringCellValue()); //老师姓名
                String teacherUsername = row.getCell(8).getStringCellValue();
                assistant.setTeacherUsername(teacherUsername);
                Teacher teacher = teacherRepository.findAllByUsername(teacherUsername);
                assistant.setTeacherId(teacher.getId().toString());
                assistant.setStatus("已审");
//                assistant.setAddress(row.getCell(9).getStringCellValue());
                assistant.setHours(row.getCell(9).getStringCellValue());
                assistant.setRequirments(row.getCell(10).getStringCellValue());
                assistant.setNote(row.getCell(11).getStringCellValue());
                assistant.setRecv(Integer.valueOf(row.getCell(12).getStringCellValue()));
                Parameter parameter = parameterRepository.findByCollegeAndGradeAndType(assistant.getCollege(), assistant.getGrade(), "助教助研");
                if (parameter == null) {
                    return "教务员未设置初始互选参数！";
                }
                //初始化
                assistant.setApplyed(0);
                assistant.setRecv(0);
                assistant.setTaskStart(parameter.getTaskStart());
                assistant.setTaskDdl(parameter.getTaskDdl());
                assistant.setStuChooseStart(parameter.getStuChooseStart());
                assistant.setStuChooseDdl(parameter.getStuChooseDdl());
                assistant.setTeaChooseStart(parameter.getTeaChooseStart());
                assistant.setTeaChooseDdl(parameter.getTeaChooseDdl());
                assistant.setMaxApply(parameter.getMaxApply());
                assistant.setMaxRecv(parameter.getMaxRecv());
                assistants.add(assistant);
            } catch (NullPointerException e) {
                return "第" + count + "行有属性为空，请填满所有属性！";
            }
            count++;
        }
        try {
            assistantRepository.saveAll(assistants);

        } catch (Exception e) {
            return "表内用户名冗余或用户名已存在！";
        }
        return "导入成功";
    }

    @Override
    public String updatePassword(Password password) {
        String username = userDetailsUtil.getUserDetails();
        User user = userRepository.findAllByUsername(username);
        String encodedPassword = user.getPassword();
        String role = user.getRole();
        if (!bCryptPasswordEncoderUtil.matches(password.getOldPassword(), encodedPassword)) {
            return "原始密码不正确！";
        }
        switch (role) {
            case "student":
                studentRepositoty.updatePasswordByStID(username, password.getNewPassword());
                break;
            case "teacher":
                teacherRepository.updatePasswordByUsername(username, password.getNewPassword());
                break;
            case "admin":
                adminRepository.updatePasswordByUsername(username, password.getNewPassword());
                break;
            case "instructor":
                instructorRepository.updatePasswordByUsername(username, password.getNewPassword());
            default:
                break;
        }
        userRepository.updatePasswordByUsername(username, bCryptPasswordEncoderUtil.encode(password.getNewPassword()));
        return "修改成功！";
    }


    private Workbook initWorkbook(HttpServletRequest request) throws FileUploadException, IOException {
        ServletFileUpload upload = new ServletFileUpload(
                new DiskFileItemFactory());
        upload.setHeaderEncoding("UTF-8");
        String filename = null;
        FileInputStream is = null;
        Workbook workbook = null;
        List<FileItem> list = upload.parseRequest(request);
        for (FileItem item : list) {
            if (!item.isFormField()) {
                filename = item.getName();
                is = (FileInputStream) item.getInputStream();
            }
        }
        try {
            assert filename != null;
            if (filename.toLowerCase().endsWith("xlsx")) {
                workbook = new XSSFWorkbook(is);
            } else if (filename.toLowerCase().endsWith("xls")) {
                workbook = new HSSFWorkbook(is);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(is);
        }
        return workbook;
    }
}
